/**
 * Copyright (c) 2006-2015, JGraph Ltd
 * Copyright (c) 2006-2015, Gaudenz Alder
 */
/**
 * Class: mxLabel
 *
 * Extends <mxShape> to implement an image shape with a label.
 * This shape is registered under <mxConstants.SHAPE_LABEL> in
 * <mxCellRenderer>.
 *
 * Constructor: mxLabel
 *
 * Constructs a new label shape.
 *
 * Parameters:
 *
 * bounds - <mxRectangle> that defines the bounds. This is stored in
 * <mxShape.bounds>.
 * fill - String that defines the fill color. This is stored in <fill>.
 * stroke - String that defines the stroke color. This is stored in <stroke>.
 * strokewidth - Optional integer that defines the stroke width. Default is
 * 1. This is stored in <strokewidth>.
 */
function mxLabel(bounds, fill, stroke, strokewidth) {
  mxRectangleShape.call(this, bounds, fill, stroke, strokewidth);
}

/**
 * Extends mxShape.
 */
mxUtils.extend(mxLabel, mxRectangleShape);

/**
 * Variable: imageSize
 *
 * Default width and height for the image. Default is
 * <mxConstants.DEFAULT_IMAGESIZE>.
 */
mxLabel.prototype.imageSize = mxConstants.DEFAULT_IMAGESIZE;

/**
 * Variable: spacing
 *
 * Default value for image spacing. Default is 2.
 */
mxLabel.prototype.spacing = 2;

/**
 * Variable: indicatorSize
 *
 * Default width and height for the indicicator. Default is 10.
 */
mxLabel.prototype.indicatorSize = 10;

/**
 * Variable: indicatorSpacing
 *
 * Default spacing between image and indicator. Default is 2.
 */
mxLabel.prototype.indicatorSpacing = 2;

/**
 * Function: init
 *
 * Initializes the shape and the <indicator>.
 */
mxLabel.prototype.init = function (container) {
  mxShape.prototype.init.apply(this, arguments);

  if (this.indicatorShape != null) {
    this.indicator = new this.indicatorShape();
    this.indicator.dialect = this.dialect;
    this.indicator.init(this.node);
  }
};

/**
 * Function: redraw
 *
 * Reconfigures this shape. This will update the colors of the indicator
 * and reconfigure it if required.
 */
mxLabel.prototype.redraw = function () {
  if (this.indicator != null) {
    this.indicator.fill = this.indicatorColor;
    this.indicator.stroke = this.indicatorStrokeColor;
    this.indicator.gradient = this.indicatorGradientColor;
    this.indicator.direction = this.indicatorDirection;
  }

  mxShape.prototype.redraw.apply(this, arguments);
};

/**
 * Function: isHtmlAllowed
 *
 * Returns true for non-rounded, non-rotated shapes with no glass gradient and
 * no indicator shape.
 */
mxLabel.prototype.isHtmlAllowed = function () {
  return (
    mxRectangleShape.prototype.isHtmlAllowed.apply(this, arguments) &&
    this.indicatorColor == null &&
    this.indicatorShape == null
  );
};

/**
 * Function: paintForeground
 *
 * Generic background painting implementation.
 */
mxLabel.prototype.paintForeground = function (c, x, y, w, h) {
  this.paintImage(c, x, y, w, h);
  this.paintIndicator(c, x, y, w, h);

  mxRectangleShape.prototype.paintForeground.apply(this, arguments);
};

/**
 * Function: paintImage
 *
 * Generic background painting implementation.
 */
mxLabel.prototype.paintImage = function (c, x, y, w, h) {
  if (this.image != null) {
    var bounds = this.getImageBounds(x, y, w, h);
    c.image(
      bounds.x,
      bounds.y,
      bounds.width,
      bounds.height,
      this.image,
      false,
      false,
      false
    );
  }
};

/**
 * Function: getImageBounds
 *
 * Generic background painting implementation.
 */
mxLabel.prototype.getImageBounds = function (x, y, w, h) {
  var align = mxUtils.getValue(
    this.style,
    mxConstants.STYLE_IMAGE_ALIGN,
    mxConstants.ALIGN_LEFT
  );
  var valign = mxUtils.getValue(
    this.style,
    mxConstants.STYLE_IMAGE_VERTICAL_ALIGN,
    mxConstants.ALIGN_MIDDLE
  );
  var width = mxUtils.getNumber(
    this.style,
    mxConstants.STYLE_IMAGE_WIDTH,
    mxConstants.DEFAULT_IMAGESIZE
  );
  var height = mxUtils.getNumber(
    this.style,
    mxConstants.STYLE_IMAGE_HEIGHT,
    mxConstants.DEFAULT_IMAGESIZE
  );
  var spacing =
    mxUtils.getNumber(this.style, mxConstants.STYLE_SPACING, this.spacing) + 5;

  if (align == mxConstants.ALIGN_CENTER) {
    x += (w - width) / 2;
  } else if (align == mxConstants.ALIGN_RIGHT) {
    x += w - width - spacing;
  } // default is left
  else {
    x += spacing;
  }

  if (valign == mxConstants.ALIGN_TOP) {
    y += spacing;
  } else if (valign == mxConstants.ALIGN_BOTTOM) {
    y += h - height - spacing;
  } // default is middle
  else {
    y += (h - height) / 2;
  }

  return new mxRectangle(x, y, width, height);
};

/**
 * Function: paintIndicator
 *
 * Generic background painting implementation.
 */
mxLabel.prototype.paintIndicator = function (c, x, y, w, h) {
  if (this.indicator != null) {
    this.indicator.bounds = this.getIndicatorBounds(x, y, w, h);
    this.indicator.paint(c);
  } else if (this.indicatorImage != null) {
    var bounds = this.getIndicatorBounds(x, y, w, h);
    c.image(
      bounds.x,
      bounds.y,
      bounds.width,
      bounds.height,
      this.indicatorImage,
      false,
      false,
      false
    );
  }
};

/**
 * Function: getIndicatorBounds
 *
 * Generic background painting implementation.
 */
mxLabel.prototype.getIndicatorBounds = function (x, y, w, h) {
  var align = mxUtils.getValue(
    this.style,
    mxConstants.STYLE_IMAGE_ALIGN,
    mxConstants.ALIGN_LEFT
  );
  var valign = mxUtils.getValue(
    this.style,
    mxConstants.STYLE_IMAGE_VERTICAL_ALIGN,
    mxConstants.ALIGN_MIDDLE
  );
  var width = mxUtils.getNumber(
    this.style,
    mxConstants.STYLE_INDICATOR_WIDTH,
    this.indicatorSize
  );
  var height = mxUtils.getNumber(
    this.style,
    mxConstants.STYLE_INDICATOR_HEIGHT,
    this.indicatorSize
  );
  var spacing = this.spacing + 5;

  if (align == mxConstants.ALIGN_RIGHT) {
    x += w - width - spacing;
  } else if (align == mxConstants.ALIGN_CENTER) {
    x += (w - width) / 2;
  } // default is left
  else {
    x += spacing;
  }

  if (valign == mxConstants.ALIGN_BOTTOM) {
    y += h - height - spacing;
  } else if (valign == mxConstants.ALIGN_TOP) {
    y += spacing;
  } // default is middle
  else {
    y += (h - height) / 2;
  }

  return new mxRectangle(x, y, width, height);
};
/**
 * Function: redrawHtmlShape
 *
 * Generic background painting implementation.
 */
mxLabel.prototype.redrawHtmlShape = function () {
  mxRectangleShape.prototype.redrawHtmlShape.apply(this, arguments);

  // Removes all children
  while (this.node.hasChildNodes()) {
    this.node.removeChild(this.node.lastChild);
  }

  if (this.image != null) {
    var node = document.createElement("img");
    node.style.position = "relative";
    node.setAttribute("border", "0");

    var bounds = this.getImageBounds(
      this.bounds.x,
      this.bounds.y,
      this.bounds.width,
      this.bounds.height
    );
    bounds.x -= this.bounds.x;
    bounds.y -= this.bounds.y;

    node.style.left = Math.round(bounds.x) + "px";
    node.style.top = Math.round(bounds.y) + "px";
    node.style.width = Math.round(bounds.width) + "px";
    node.style.height = Math.round(bounds.height) + "px";

    node.src = this.image;

    this.node.appendChild(node);
  }
};
